package com.newly.center.business.task;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.ejlchina.okhttps.GsonMsgConvertor;
import com.ejlchina.okhttps.HTTP;
import com.ejlchina.okhttps.HttpResult;
import com.newly.center.business.compenont.InterfaceAddressConfig;
import com.newly.center.business.compenont.WebSocketServer;
import com.newly.center.business.service.CheckRecordService;
import com.newly.center.business.service.SiteService;
import com.newly.common.base.entity.business.Vo.CheckRecordVo;
import com.newly.common.base.entity.business.Vo.DetailsVo;
import com.newly.common.base.entity.business.Vo.SrcVo;
import com.newly.common.base.entity.device.po.DevicePo;
import com.newly.common.base.entity.sys.dict.po.DictPo;
import com.newly.common.mapper.business.SiteMapper;
import com.newly.common.mapper.sys.DeviceMapper;
import com.newly.common.mapper.sys.DictMapper;
import com.newly.transfer.redis.utils.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.stream.Collectors;

/**
 * @anthor ljq
 * @date 2021/12/01 14:01
 */
@Component
public class DeviceTask {

    @Autowired
    RedisUtils redisUtils;
    @Autowired
    DeviceMapper deviceMapper;
    @Autowired
    DictMapper dictMapper;
    @Autowired
    SiteMapper siteMapper;
    @Autowired
    CheckRecordService checkRecordService;
    @Autowired
    SiteService siteService;
    int a = 0;

    //@Scheduled(cron = "0/30 * * * * ?")
    public void push(){
        CopyOnWriteArraySet<WebSocketServer> webSocketServerSet = WebSocketServer.getWebSocketServerSet();

        if(a==0){
            a=a+1;
            webSocketServerSet.forEach(t -> {
                try {
                    DetailsVo<CheckRecordVo> detailsById = checkRecordService.getDetailsById(33);
                    JSONObject data = new JSONObject();
                    data.put("type","all");
                    data.put("data",detailsById);
                    data.put("isOverload",1);
                    t.SendMessage(JSONUtil.toJsonStr(data));
                    try {
                        Thread.sleep(5000);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                    data.put("isBlacklist",1);
                    t.SendMessage(JSONUtil.toJsonStr(data));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
        else {
            a=a-1;
            webSocketServerSet.forEach(t -> {
                try {
                    DetailsVo<CheckRecordVo> detailsById = checkRecordService.getDetailsById(45);
                    JSONObject data = new JSONObject();
                    data.put("type","all");
                    data.put("data",detailsById);
                    data.put("isOverload",1);
                    t.SendMessage(JSONUtil.toJsonStr(data));
                    try {
                        Thread.sleep(5000);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                    data.put("isBlacklist",1);
                    t.SendMessage(JSONUtil.toJsonStr(data));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
    }

    /**
     * 定时轮询更新设备在线状态
     * cron表达式：Seconds Minutes Hours DayofMonth Month DayofWeek [Year]
     */
    @Scheduled(cron = "0 0/30 * * * ?")
    private void deviceStateLister(){
        List<DictPo> dictPos = dictMapper.selectList(new QueryWrapper<DictPo>().lambda().eq(DictPo::getCode, "10027"));
        if(dictPos.size()>0){
            if("1".equals(dictPos.get(0).getValue())){
                return;
            }
        }
        else {
            return;
        }
        System.out.println("----------开始检查设备状态----------");
        String gatewayStr = redisUtils.get("mqttGateway",String.class);
        JSONArray tmpGateway = JSONUtil.parseArray(gatewayStr);
        for(Object key:tmpGateway){
            //从redis移除离线网关
            String token = redisUtils.get("mqtt" + key.toString(), String.class);
            if(token==null){
                gatewayStr=gatewayStr.replace(",\""+key.toString()+"\"","");
                gatewayStr=gatewayStr.replace("\""+key.toString()+"\",","");
            }
        }
        JSONArray gateway = JSONUtil.parseArray(gatewayStr);
        redisUtils.set("mqttGateway",JSONUtil.toJsonStr(gateway));

        List<DevicePo> devicePos = deviceMapper.selectList(new QueryWrapper<DevicePo>().lambda().eq(DevicePo::getType, 1));
        List<String> deviceKeyList = devicePos.stream().map(DevicePo::getProductKey).collect(Collectors.toList());
        for(Object key:gateway){
            //新网关存库
            if(!deviceKeyList.contains(key.toString())){
                DevicePo newGateway = new DevicePo();
                newGateway.setSiteId(0L);
                newGateway.setName("新网关-"+key);
                newGateway.setType(1);
                newGateway.setDeviceStatus("1");
                newGateway.setIsAvailable("1");
                newGateway.setIsDeleted("0");
                newGateway.setProductKey(key.toString());
                newGateway.setCreateTime(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()));
                deviceMapper.insert(newGateway);
            }
        }

        //网关下线
        List<String> offlineProductKey = devicePos.stream().filter(x -> !gateway.contains(x.getProductKey())).map(DevicePo::getProductKey).collect(Collectors.toList());
        if(offlineProductKey.size()!=0){
            UpdateWrapper<DevicePo> siteOfflineUpdateWrapper = new UpdateWrapper<>();
            siteOfflineUpdateWrapper.in("product_key",offlineProductKey);
//            siteOfflineUpdateWrapper.ne("type",1);//不等于网关
            siteOfflineUpdateWrapper.eq("type", 1);//等于网关
            siteOfflineUpdateWrapper.set("device_status",0);
            deviceMapper.update(null,siteOfflineUpdateWrapper);
        }
        //网关上线
        List<String> onlineProductKey = devicePos.stream().filter(x -> gateway.contains(x.getProductKey())).map(DevicePo::getProductKey).collect(Collectors.toList());
        if(onlineProductKey.size()!=0){
                UpdateWrapper<DevicePo> siteOnlineUpdateWrapper = new UpdateWrapper<>();
                siteOnlineUpdateWrapper.in("product_key", onlineProductKey);
                siteOnlineUpdateWrapper.eq("type", 1);//等于网关
                siteOnlineUpdateWrapper.set("device_status", 1);
                deviceMapper.update(null, siteOnlineUpdateWrapper);
        }
        for(String item : deviceKeyList){
            List<DevicePo> devicePoList = this.deviceMapper.selectList(new LambdaQueryWrapper<DevicePo>()
                    .ne(DevicePo::getType,1).eq(DevicePo::getProductKey,item));
            List<String> gbIds = devicePoList.stream().map(DevicePo::getGbId).collect(Collectors.toList());
            if(gbIds.size()==0){
                continue;
            }
            for (String gbId : gbIds) {
                //查询src通道
                HTTP http = HTTP.builder().baseUrl(InterfaceAddressConfig.baseDomain).addMsgConvertor(new GsonMsgConvertor()).build();
                HttpResult.Body body = http.sync(InterfaceAddressConfig.url)
                        .addUrlPara("action", "query_channel")
                        .addUrlPara("id",gbId)
                        .get()
                        .getBody();
                SrcVo srcVo = body.toBean(SrcVo.class);
                int code = srcVo.getCode();
                UpdateWrapper<DevicePo> onlineUpdateWrapper = new UpdateWrapper<>();
                onlineUpdateWrapper.eq("product_key",item+"");
                onlineUpdateWrapper.ne("type",1);
                onlineUpdateWrapper.eq("gb_id",gbId);
                onlineUpdateWrapper.set("device_status",code == 0 ? 1 : 0);
                onlineUpdateWrapper.set("update_time", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()));
                deviceMapper.update(null,onlineUpdateWrapper);
            }
//            String token = redisUtils.get("mqtt"+item,String.class);
//
//            JSONObject result = new JSONObject();
//            result.put("version","1.0");
//            result.put("id",item+"");
//            result.put("token",token);
//
//            //本地调试用
//            JSONObject params = new JSONObject();
////            JSONArray slot = new JSONArray();
////            slot.add(1);
////            slot.add(999);
////            params.put("slot",slot);
//            String slot="{\"slot\":null}";
//            result.put("params",JSONUtil.parseObj(slot));
//
//            //列表查询网关设备，利用返回的state判断离线
//            String requestTopic = "/sys/device/"+ item+"/command/request/request-id=0x10000007";
//            String responseTopic = "/sys/device/"+ item+"/command/response/request-id=0x10000007";
//            //避免mqtt频繁发布
//            try {
//                Thread.sleep(1000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            MqttUtils.publishMessage(requestTopic,result,1);
//            R response =  ReturnResult.getResult(responseTopic,redisUtils);
//            if(response.getCode()==0){
//                JSONObject data = (JSONObject) response.getData();
//                List<Map<String, Object>> maps = (List<Map<String, Object>>) data.get("device-list");
//
//                List<Integer> onlineSlot = maps.stream().filter(x -> "online".equals(x.get("state"))).map(x -> (int)x.get("slot")).collect(Collectors.toList());
//                List<Integer> offlineSlot = maps.stream().filter(x -> "offline".equals(x.get("state"))).map(x -> (int)x.get("slot")).collect(Collectors.toList());
//                //根据设备槽位查询设备记录
//                List<DevicePo> devicePoList = this.deviceMapper.selectList(new LambdaQueryWrapper<DevicePo>().in(DevicePo::getSlot,onlineSlot));
//                if (ObjectUtil.isEmpty(devicePoList))
//                    throw new NewlyException("定时器DeviceTask的deviceStateLister方法中根据设备槽位查询设备记录为空！");
//                List<String> gbIds = devicePoList.stream().map(DevicePo::getGbId).collect(Collectors.toList());
//
//                if(onlineSlot.size()>0){
//                    for (String gbId : gbIds) {
//                        //查询src通道
//                        HTTP http = HTTP.builder().baseUrl(InterfaceAddressConfig.baseDomain).addMsgConvertor(new GsonMsgConvertor()).build();
//                        HttpResult.Body body = http.sync(InterfaceAddressConfig.url)
//                                .addUrlPara("action", "query_channel")
//                                .addUrlPara("id",gbId)
//                                .get()
//                                .getBody();
//                        SrcVo srcVo = body.toBean(SrcVo.class);
//                        int code = srcVo.getCode();
//                        UpdateWrapper<DevicePo> onlineUpdateWrapper = new UpdateWrapper<>();
//                        onlineUpdateWrapper.in("slot",onlineSlot);
//                        onlineUpdateWrapper.eq("product_key",item+"");
//                        onlineUpdateWrapper.ne("type",1);
//                        onlineUpdateWrapper.eq("gb_id",gbId);
//                        onlineUpdateWrapper.set("device_status",code == 0 ? 1 : 0);
//                        onlineUpdateWrapper.set("update_time", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()));
//                        deviceMapper.update(null,onlineUpdateWrapper);
//                    }
//                }
//                if(offlineSlot.size()>0){
//                    UpdateWrapper<DevicePo> offlineUpdateWrapper = new UpdateWrapper<>();
//                    offlineUpdateWrapper.in("slot",offlineSlot);
//                    offlineUpdateWrapper.eq("product_key",item+"");
//                    offlineUpdateWrapper.ne("device_status",1);
//                    offlineUpdateWrapper.set("device_status",0);
//                    offlineUpdateWrapper.set("update_time", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()));
//                    deviceMapper.update(null,offlineUpdateWrapper);
//                }
//
//            }
        }

        System.out.println("--------------检查结束--------------");
    }
}
